﻿//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="DylanBox">
// Copyright (c) DylanBox Corporation. All rights reserved.
// </copyright>
// <summary></summary>
// <reference>
//    C#异步调用四大方法详解
// </reference>
// <author>Dylan</author>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AsyncDemo
{
    class Program
    {
        public delegate string AsyncDelegate(int callDuration, out int threadId);

        static void Main(string[] args)
        {
            //DoAsyncWork1();
            //DoAsyncWork2();
            //DoAsyncWork3();
            DoAsyncwork4();
        }

        /// <summary>
        /// EndInvoke 等待异步调用
        /// </summary>
        public static void DoAsyncWork1()
        {
            Console.WriteLine("Do anync work 1");

            // The asynchronous method puts the thread id here.  
            int threadId;

            Functions func = new Functions();

            AsyncDelegate dlgt = new AsyncDelegate(func.TestMethod);

            // Initiate the asychronous call. 
            IAsyncResult ar = dlgt.BeginInvoke(3000, out threadId, null, null);
            
            Thread.Sleep(1000);
            Console.WriteLine("Main thread {0} does some work.", AppDomain.GetCurrentThreadId());

            // Call EndInvoke to Wait for  
            // the asynchronous call to complete,  
            // and to retrieve the results.  
            string ret = dlgt.EndInvoke(out threadId, ar);

            Console.WriteLine("The call executed on thread {0},   with return value \"{1}\".", threadId, ret);

            Console.Read();
        }

        /// <summary>
        /// WaitHandle 等待异步调用
        /// </summary>
        public static void DoAsyncWork2()
        {
            Console.WriteLine("Do anync work 2");

            // The asynchronous method puts the thread id here.  
            int threadId;

            Functions func = new Functions();

            AsyncDelegate dlgt = new AsyncDelegate(func.TestMethod);

            // Initiate the asychronous call. 
            IAsyncResult ar = dlgt.BeginInvoke(3000, out threadId, null, null);
            
            Thread.Sleep(1000);
            Console.WriteLine("Main thread {0} does some work.", AppDomain.GetCurrentThreadId());

            // Wait for the WaitHandle to become signaled.  
            ar.AsyncWaitHandle.WaitOne();

            // Perform additional processing here.
            // ...  

            // Call EndInvoke to retrieve the results. 
            string ret = dlgt.EndInvoke(out threadId, ar);  

            Console.WriteLine("The call executed on thread {0},   with return value \"{1}\".", threadId, ret);

            Console.Read();
        }

        /// <summary>
        /// Async Polling
        /// </summary>
        public static void DoAsyncWork3()
        {
            Console.WriteLine("Do anync work 3");

            // The asynchronous method puts the thread id here.  
            int threadId;   
            
            // Create an instance of the test class.  
            Functions func = new Functions();
            
            // Create the delegate.  
            AsyncDelegate dlgt = new AsyncDelegate(func.TestMethod);       
            
            // Initiate the asychronous call.  
            IAsyncResult ar = dlgt.BeginInvoke(3000, out threadId, null, null);   
            
            // Poll while simulating work.  
            while(ar.IsCompleted == false) 
            {  
                Thread.Sleep(10);  
            }   
            
            // Call EndInvoke to retrieve the results.  
            string ret = dlgt.EndInvoke(out threadId, ar);   
            Console.WriteLine("The call executed on thread {0},   with return value \"{1}\".", threadId, ret);

            Console.Read();
        }

        /// <summary>
        /// Async callback
        /// </summary>
        public static void DoAsyncwork4()
        {
            // Asynchronous method puts the thread id here.  
            int threadId;   
           
            // Create an instance of the test class. 
            Functions func = new Functions();  
            
            // Create the delegate.  
            AsyncDelegate dlgt = new AsyncDelegate(func.TestMethod); 
        
            // Initiate the asychronous call.  Include an AsyncCallback              
            // delegate representing the callback method, 
            // and the data needed to call EndInvoke, dlgt 传递启动调用时曾使用的委托，以便回调方法能够调用 EndInvoke。
            IAsyncResult ar = dlgt.BeginInvoke(30000,  out threadId,   new AsyncCallback(CallbackMethod),  dlgt );  
            
            Console.WriteLine("Press Enter to close application.");              
            Console.ReadLine(); 
        }          

        // Callback method must have the same signature as the  
        // AsyncCallback delegate. 
        private static void CallbackMethod(IAsyncResult ar) 
        {
            int threadId;
            // Retrieve the delegate. 
            AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;  
            // Call EndInvoke to retrieve the results. 
            string ret = dlgt.EndInvoke(out threadId, ar);   
            Console.WriteLine("The call executed on thread {0},   with return value \"{1}\".", threadId, ret); 
        }  
    }
}
